﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Main.Structure;
using Main.Substructure;
using Main.Menus.Submenus;

namespace Main.Menus
{
    public partial class AppointmentManager : Form
    {
        // Local variables:
        #region Submenus
        private AddAppointment AA; // Submenu variable
        private ManageAppointment MA; // Submenu variable
        #endregion
        private Timer dataAdditionTimer = new Timer(); // Timer to refresh appointments while in the AA screen
        private Timer dataModificationTimer = new Timer(); // Timer to refresh appointments while in the MA screen
        private int apptCount = 0; // Counter
        private object _syncObject = new object(); // To prevent cross-threading or multiple method calls.

        /// <summary>
        /// Class Constructor
        /// Calls any initialization code.
        /// </summary>
        public AppointmentManager()
        {
            InitializeComponent();
            dataAdditionTimer.Tick += new EventHandler(dataAdditionTimer_Tick);
            dataModificationTimer.Tick += new EventHandler(dataModificationTimer_Tick);
            Main();
        }


        /// <summary>This method contains all of the code we want to run before the form is loaded.</summary>
        private void Main()
        {
            PopulateApptList();
        }

        /// <summary>This method loads all of the appointments into an easily readable list.</summary>
        private bool PopulateApptList()
        {
            try
            {
                lock (_syncObject)
                {
                    listViewAppts.Items.Clear();

                    foreach (Appointment appt in Kernel.Appointments.Values)
                    {
                        ListViewItem listItem = new ListViewItem();
                        listItem.Text = appt.Month.ToString();
                        listItem.SubItems.Add(appt.Day + "(" + appt.DayOfWeek + ")");
                        listItem.SubItems.Add(appt.Year.ToString());
                        #region Hour Check
                        var hour = 0;
                        var timeOfDay = "AM";
                        if (appt.Hour <= 12)
                            hour = appt.Hour;
                        else { hour = appt.Hour - 12; timeOfDay = "PM"; }
                        #endregion
                        var minute = appt.Minute;
                        if (minute >= 10)
                            listItem.SubItems.Add(hour + ":" + appt.Minute + timeOfDay);
                        else
                            listItem.SubItems.Add(hour + ":0" + appt.Minute + timeOfDay);

                        listItem.SubItems.Add(appt.Ticks.ToString());

                        listViewAppts.Items.Add(listItem);
                    }
                    return true;
                }
            }
            catch (Exception) { return false; }
        }

        /// <summary>
        /// This method is executed when the user clicks the "Add Appointment" button.
        /// This method calls the submenu that handles creating new appointments and
        /// starts the timer to see if there are any refreshments needed to the appt list.
        /// </summary>
        private void btnAddAppt_Click(object sender, EventArgs e)
        {
            lock (_syncObject)
            {
                if (AA != null && !AA.Visible)
                {
                    AA.Dispose();
                    AA = new AddAppointment();
                    Utilities.LaunchMenu(AA);

                    apptCount = Kernel.Appointments.Count;
                    dataAdditionTimer.Interval = 500;
                    dataAdditionTimer.Start();
                }
                if (AA == null)
                {
                    AA = new AddAppointment();
                    Utilities.LaunchMenu(AA);

                    apptCount = Kernel.Appointments.Count;
                    dataAdditionTimer.Interval = 500;
                    dataAdditionTimer.Start();
                }
            }
        }

        /// <summary>
        /// This method is executed when the user clicks the "Remove Appointment" button.
        /// This method calls the Database.Appointments.Remove method and then refreshes the screen once done.
        /// </summary>
        private void btnRemove_Click(object sender, EventArgs e)
        {
            lock (_syncObject)
            {
                if (listViewAppts.SelectedItems.Count != 1)
                    return;

                foreach (ListViewItem item in listViewAppts.SelectedItems)
                {
                    long ticks = 0;
                    Int64.TryParse(item.SubItems[4].Text, out ticks);

                    if (ticks == 0)
                        return;

                    Appointment appt;
                    Kernel.Appointments.TryGetValue(ticks, out appt);
                    if (!Database.Appointments.Remove(appt))
                        Utilities.Message("Appointment could not be removed.", "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    else
                        Utilities.Message("Appointment was successfully removed!", "Appointment Removed", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);

                    PopulateApptList();
                }
            }
        }


        /// <summary>
        /// This method is executed when the user clicks the "View Appointment" button.
        /// This method brings up the submenu to view appointments and passes the appointment to view.
        /// </summary>
        private void btnView_Click(object sender, EventArgs e)
        {
            lock (_syncObject)
            {
                if (listViewAppts.SelectedItems.Count != 1)
                    return;

                Appointment appt = null;

                foreach (ListViewItem item in listViewAppts.SelectedItems)
                {
                    long ticks = 0;
                    Int64.TryParse(item.SubItems[4].Text, out ticks);

                    if (ticks == 0)
                        return;

                    Kernel.Appointments.TryGetValue(ticks, out appt);
                }
                if (MA != null && !MA.Visible && appt != null)
                {
                    MA.Dispose();
                    MA = new ManageAppointment(appt, false);
                    Utilities.LaunchMenu(MA);
                }
                if (MA == null && appt != null)
                {
                    MA = new ManageAppointment(appt, false);
                    Utilities.LaunchMenu(MA);
                }
            }
        }

        /// <summary>
        /// This method is executed when the user clicks the "Modify Appointment" button.
        /// This method brings up the submenu to modify appointments and passes the appointment to modify.
        /// </summary>
        private void btnModify_Click(object sender, EventArgs e)
        {
            lock (_syncObject)
            {
                if (listViewAppts.SelectedItems.Count != 1)
                    return;

                Appointment appt = null;

                foreach (ListViewItem item in listViewAppts.SelectedItems)
                {
                    long ticks = 0;
                    Int64.TryParse(item.SubItems[4].Text, out ticks);

                    if (ticks == 0)
                        return;

                    Kernel.Appointments.TryGetValue(ticks, out appt);
                }
                if (MA != null && !MA.Visible && appt != null)
                {
                    MA.Dispose();
                    MA = new ManageAppointment(appt, true);
                    Utilities.LaunchMenu(MA);

                    apptCount = Kernel.Appointments.Count;
                    dataModificationTimer.Interval = 500;
                    dataModificationTimer.Start();
                }
                if (MA == null && appt != null)
                {
                    MA = new ManageAppointment(appt, true);
                    Utilities.LaunchMenu(MA);

                    apptCount = Kernel.Appointments.Count;
                    dataModificationTimer.Interval = 500;
                    dataModificationTimer.Start();
                }
            }
        }

        /// <summary>
        /// This method is called on every tick of the dataAdditionTimer when started.
        /// This checks to see if any appointments have been added/removed and if so, re-populates
        /// the appointment list.
        /// </summary>
        private void dataAdditionTimer_Tick(object sender, EventArgs e)
        {
            if (apptCount != Kernel.Appointments.Count)
            {
                PopulateApptList();
                apptCount = Kernel.Appointments.Count;
            }
            if (AA != null)
            {
                if (AA.IsDisposed || !AA.Visible)
                    dataAdditionTimer.Stop();
            }
            else { dataAdditionTimer.Stop(); }
        }

        /// <summary>
        /// This method is called on every tick of the dataAdditionTimer when started.
        /// This checks to see if any appointments have been modified and if so, re-populates
        /// the appointment list.
        /// </summary>
        private void dataModificationTimer_Tick(object sender, EventArgs e)
        {
            if (MA == null || !MA.Visible || MA.IsDisposed)
            {
                if (MA != null)
                    MA.Dispose();
                PopulateApptList();
                dataModificationTimer.Stop();
            }
        }
    }
}
